import { AxiosResponse } from 'axios';
import _ from 'lodash';

export interface IAjaxResponse {
  success: boolean;

  result?: any;

  targetUrl?: string;

  error?: IErrorInfo;

  unAuthorizedRequest: boolean;

  __abp: boolean;
}
export interface IValidationErrorInfo {
  message: string;

  members: string[];
}

export interface IErrorInfo {
  code: number;

  message: string;

  details: string;

  validationErrors: IValidationErrorInfo[];
}

class AbpHttpConfigurationService {
  defaultError = <IErrorInfo>{
    message: 'An error has occurred!',
    details: 'Error details were not sent by server.',
  };

  defaultError401 = <IErrorInfo>{
    message: 'You are not authenticated!',
    details: 'You should be authenticated (sign in) in order to perform this operation.',
  };

  defaultError403 = <IErrorInfo>{
    message: 'You are not authorized!',
    details: 'You are not allowed to perform this operation.',
  };

  defaultError404 = <IErrorInfo>{
    message: 'Resource not found!',
    details: 'The resource requested could not be found on the server.',
  };

  logError(error: IErrorInfo): void {
    abp.log.error(error);
  }
  showError(error: IErrorInfo): any {
    if (error.details) {
      return abp.message.error(error.details, error.message || this.defaultError.message);
    } else {
      return abp.message.error(error.message || this.defaultError.message);
    }
  }

  handleTargetUrl(targetUrl: string): void {
    if (!targetUrl) {
      location.href = '/';
    } else {
      if (targetUrl === '/license/config') {
        targetUrl = '/account/set-license';
      }

      location.href = targetUrl;
    }
  }

  handleUnAuthorizedRequest(messagePromise: any, targetUrl?: string) {
    const self = this;

    if (messagePromise) {
      messagePromise.done(() => {
        this.handleTargetUrl(targetUrl || '/');
      });
    } else {
      self.handleTargetUrl(targetUrl || '/');
    }
  }

  handleNonAbpErrorResponse(response: AxiosResponse) {
    const self = this;
    //debugger;
    switch (response.status) {
      case 401:
        self.handleUnAuthorizedRequest(self.showError(self.defaultError401), '/');
        break;
      case 403:
        self.showError(self.defaultError403);
        break;
      case 404:
        self.showError(self.defaultError404);
        break;
      default:
        self.showError(self.defaultError);
        break;
    }
  }

  handleAbpResponse(response: AxiosResponse, ajaxResponse: IAjaxResponse): AxiosResponse {
    const newResponse = _.cloneDeep(response);
    newResponse.data = ajaxResponse.result;
    if (ajaxResponse.success) {
      if (ajaxResponse.targetUrl) {
        this.handleTargetUrl(ajaxResponse.targetUrl);
      }
    } else {
      if (!ajaxResponse.error) {
        ajaxResponse.error = this.defaultError;
      }
      this.logError(ajaxResponse.error);
      this.showError(ajaxResponse.error);

      if (response.status === 401) {
        this.handleUnAuthorizedRequest(null, ajaxResponse.targetUrl);
      }
    }

    return newResponse;
  }

  getAbpAjaxResponseOrNull(response: AxiosResponse): IAjaxResponse | null {
    if (!response || !response.headers) {
      return null;
    }

    const contentType = response.headers['Content-Type'] || response.headers['content-type'];
    if (!contentType) {
      abp.log.warn('Content-Type is not sent!');
      return null;
    }

    if (contentType.indexOf('application/json') < 0) {
      abp.log.warn('Content-Type is not application/json: ' + contentType);
      return null;
    }

    const responseObj = JSON.parse(JSON.stringify(response.data));
    if (!responseObj.__abp) {
      return null;
    }

    return responseObj as IAjaxResponse;
  }
}

const abpHttpConfiguration = new AbpHttpConfigurationService();

export default abpHttpConfiguration;
